package com.apes.autoparts.supplier.dataCenter;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.apes.autoparts.supplier.platform.SupplierPlatformItem;
import com.apes.autoparts.supplier.platform.SupplierPlatformItemRepository;
import com.apes.autoparts.supplier.todo.SupplierPlatformTodoService;
import com.apes.framework.api.DomainService;
import com.apes.framework.api.SpringManager;
import com.apes.framework.jpa.generator.service.SequenceService;
import com.apes.framework.plugin.esb.api.SimpleRequest;
import com.apes.framework.plugin.mq.MQUtil;
import com.apes.framework.util.CronExpression;
import com.apes.framework.util.DateUtil;
import com.apes.framework.util.MapUtil;
import com.apestech.framework.json.JSON;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.text.ParseException;
import java.util.*;
import java.util.stream.Collectors;

/**
 * Created by lishikun on 2021/5/19 17:00
 */
@Service("dcBusinessinfoService")
public class DCBusinessinfoService<T, R> extends DataCenterApi<T, R>{
    @Autowired
    private SupplierPlatformItemRepository supplierPlatformItemRepository;

    @Autowired
    private SupplierPlatformTodoService todoService;


    @Autowired
    SequenceService sequenceService;

    // 重点更新字段
    private final List<String> importantFields = Arrays.asList("pjbrand", "pjfactory", "pjcode");

    /**
     * 处理数据中心数据
     * @param request
     */

    public void handHeap(SimpleRequest request) {
        JSONArray data = request.getJO().getJSONArray("data");
        String supplierPlatformId = request.getJO().getString("supplierPlatformItemId");
        SupplierPlatformItem supplierPlatformItem = supplierPlatformItemRepository.findOne(supplierPlatformId);
        List<String> pjid = data.stream().map(v -> {
            JSONObject json = (JSONObject) v;
            return json.getString("ID");
        }).collect(Collectors.toList());
        JSONObject param = new JSONObject();

        List<Map> dcBusinessinfos = pjid.size() != 0 ? dcBusinessinfoRepository.findByIdsAndSupplierPlatformItem(pjid, supplierPlatformId) : new ArrayList<>();
        Map map = new HashMap();
        for (Map o : dcBusinessinfos) {
            JSONObject json = new JSONObject(o);
            map.put(json.getString("DCID"), json);
        }

        // 获取属于新建的数据
        JSONArray createJsonArray = data.stream().filter(v -> {
            JSONObject json = (JSONObject) v;
            if (map.get(json.getString("ID")) == null)
                return true;
            return false;
        }).collect(Collectors.toCollection(JSONArray::new));
        // 获取属于更新的数据
        JSONArray updateJsonArray = data.stream().filter(v -> {
            JSONObject json = (JSONObject) v;
            if (map.get(json.getString("ID")) != null)
                return true;
            return false;
        }).collect(Collectors.toCollection(JSONArray::new));
        if(request.getJO().get("lastData") != null &&
                request.getJO().getBooleanValue("lastData"))
            map.put("lastData", true);
        saveUpdateData(updateJsonArray, supplierPlatformItem, map);
        saveCreateData(createJsonArray, supplierPlatformItem, map);
        if(request.getJO().get("lastData") != null &&
                request.getJO().getBooleanValue("lastData") &&
                "synTotal".equals(request.getJO().getString("action")))
            deleteData(supplierPlatformItem);
    }


    /***
     * 保存属于更新的数据和推送待办
     * @param
     * @param supplierPlatformItem
     * @param
     */

    private void saveUpdateData(JSONArray updateJsonArray, SupplierPlatformItem supplierPlatformItem, Map map) {
        List<DCBusinessinfo> dcBusinessinfos = new ArrayList<>();
        JSONArray importantAttribute = new JSONArray();
        JSONArray update = new JSONArray();
        for (Object o : updateJsonArray) {
            JSONObject newDCBusinessinfo = (JSONObject) o;
            JSONObject oldDCBusinessinfo = (JSONObject) map.get(newDCBusinessinfo.getString("ID"));
            DCBusinessinfo dcBusinessinfo = dcBusinessinfoRepository.findOne(oldDCBusinessinfo.getString("ID"));
            jsonToDCBusinessinfo(newDCBusinessinfo, dcBusinessinfo);
            if (checkImportantUpdate(newDCBusinessinfo, oldDCBusinessinfo))
                importantAttribute.add(newDCBusinessinfo);
            else {
                update.add(newDCBusinessinfo);
            }
            dcBusinessinfo.setSupplierPlatformItem(supplierPlatformItem);
            dcBusinessinfos.add(dcBusinessinfo);
        }
        todos(importantAttribute, supplierPlatformItem,"importUpdate", map);
        todos(update, supplierPlatformItem,"update", map);
        dcBusinessinfoRepository.save(dcBusinessinfos);
    }

    private void todos(JSONArray newDCBusinessinfos, SupplierPlatformItem supplierPlatformItem, String property, Map map) {
        if (newDCBusinessinfos.size() == 0 ) return;

        JSONObject param = new JSONObject();
        param.put("property", property);
        param.put("supplierPlatformItemId", supplierPlatformItem.getId());
        List<JSONObject> collect = newDCBusinessinfos.stream().map(o -> {
            JSONObject newDCBusinessinfo = (JSONObject) o;
            JSONObject oldDCBusinessinfo = (JSONObject) map.get(newDCBusinessinfo.getString("ID"));
            JSONObject todo =  new JSONObject();
            JSONObject parse = new JSONObject();
            JSONObject supplierItem = new JSONObject();
            supplierItem.put("id", supplierPlatformItem.getId());
            todo.put("source", String.valueOf((newDCBusinessinfo.getString("ID"))));
            todo.put("supplierPlatformItem", supplierItem);
            todo.put("oldBrandName", oldDCBusinessinfo != null ? oldDCBusinessinfo.getString("BRAND_NAME") : "");
            todo.put("brandName", newDCBusinessinfo.getString("BRAND_NAME"));
            todo.put("oldOriginPlace",oldDCBusinessinfo != null ? oldDCBusinessinfo.getString("ORIGIN") :"");
            todo.put("originPlace", newDCBusinessinfo.getString("ORIGIN"));
            todo.put("oldPartCode", oldDCBusinessinfo != null ? oldDCBusinessinfo.getString("BUSINESS_ID") : "");
            todo.put("partCode", newDCBusinessinfo.getString("BUSINESS_ID"));
            todo.put("oldPartCodeName", oldDCBusinessinfo != null ? oldDCBusinessinfo.getString("PART_NAME") : "");
            todo.put("partCodeName", newDCBusinessinfo.getString("PART_NAME"));
            todo.put("oldUnit", oldDCBusinessinfo != null ? oldDCBusinessinfo.getString("UOM_NAME") : "");
            todo.put("unit", newDCBusinessinfo.getString("UOM_NAME"));
            todo.put("stockQty", newDCBusinessinfo.getDoubleValue("INVENTORY_QUANTITY"));
            todo.put("untaxPrice", newDCBusinessinfo.getDoubleValue("UNTAX_PRICE"));
            todo.put("batch", DateUtil.format(new Date(), DateUtil.SHOW_DATE_NUMBER_FORMAT));

            if (newDCBusinessinfo.get("CONTRAST_BRAND_ID") == null &&
                    newDCBusinessinfo.get("CATEGORY_ID") == null &&
                    newDCBusinessinfo.get("CONTRAST_ORIGIN") == null &&
                    newDCBusinessinfo.get("CONTRAST_PART_ID") == null
            ) {return todo;}
            JSONObject brand = new JSONObject();
            brand.put("id", newDCBusinessinfo.getString("CONTRAST_BRAND_ID"));
            JSONObject category = new JSONObject();
            category.put("id", newDCBusinessinfo.getString("CATEGORY_ID"));
            parse.put("contrastBrand", brand);
            parse.put("contrastCategory", category);
            parse.put("contrastOriginPlace", newDCBusinessinfo.getString("CONTRAST_ORIGIN"));
            parse.put("contrastPartCode", newDCBusinessinfo.getString("CONTRAST_PART_ID"));
            todo.put("todoParse", parse);
            return todo;
        }).collect(Collectors.toList());
        param.put("data", collect);
        param.put("lastData", map.get("lastData") != null ? map.get("lastData") : null);
        String topic;
        if ( !property.equals("create"))
            topic = "auto.supplierPlatform.inserts";
        else topic = "auto.supplierPlatform.createTodos";
        MQUtil.publish(topic, "供应商待办数据处理", param);

        // 自测使用
//        if (property.equals("create"))
//            SpringManager.getBean(DomainService.class).invoke("auto.supplierPlatformTodo.createTodos", param);
//        else {
//            SimpleRequest request = new SimpleRequest();
//            request.setData(param);
//            todoService.inserts(request);
//        }

    }

    private void jsonToDCBusinessinfo(JSONObject newDCBusinessinfo, DCBusinessinfo dcBusinessinfo) {
        dcBusinessinfo.setBRAND_MODEL(newDCBusinessinfo.getString("BRAND_MODEL"));
        dcBusinessinfo.setBRAND_NAME(newDCBusinessinfo.getString("BRAND_NAME"));
        dcBusinessinfo.setBUSINESS_ID(newDCBusinessinfo.getString("BUSINESS_ID"));
        dcBusinessinfo.setBZHL(newDCBusinessinfo.getString("BZHL"));
        dcBusinessinfo.setDCID(newDCBusinessinfo.getString("ID"));
        dcBusinessinfo.setINVENTORY_QUANTITY(newDCBusinessinfo.get("INVENTORY_QUANTITY")!= null ? newDCBusinessinfo.getDoubleValue("INVENTORY_QUANTITY"): 0);
        dcBusinessinfo.setONSHELVES(newDCBusinessinfo.getString("ONSHELVES"));
        dcBusinessinfo.setLRRQ_SJ(newDCBusinessinfo.getString("LRRQ_SJ"));
        dcBusinessinfo.setORIGIN(newDCBusinessinfo.getString("ORIGIN"));
        dcBusinessinfo.setPART_NAME(newDCBusinessinfo.getString("PART_NAME"));
        dcBusinessinfo.setPRODUCT_DESCRIPTION(newDCBusinessinfo.getString("PRODUCT_DESCRIPTION"));
        dcBusinessinfo.setQUALITY_NAME(newDCBusinessinfo.getString("QUALITY_NAME"));
        dcBusinessinfo.setSIZES(newDCBusinessinfo.getString("SIZES"));
        dcBusinessinfo.setSUPPLIER_ID(newDCBusinessinfo.getString("SUPPLIER_ID"));
        dcBusinessinfo.setSUPPLIER_NAME(newDCBusinessinfo.getString("SUPPLIER_NAME"));
        dcBusinessinfo.setTS01(newDCBusinessinfo.getString("TS01"));
        dcBusinessinfo.setUNIVERSAL_PART_NUMBER(newDCBusinessinfo.getString("UNIVERSAL_PART_NUMBE"));
        dcBusinessinfo.setUNTAX_PRICE(newDCBusinessinfo.get("UNTAX_PRICE") != null ? newDCBusinessinfo.getDoubleValue("UNTAX_PRICE") : 0);
        dcBusinessinfo.setUOM_NAME(newDCBusinessinfo.getString("UOM_NAME"));
        DCBusinessinfoContrast contrast = dcBusinessinfo.getDcBusinessinfoContrast() != null ?
                                            dcBusinessinfo.getDcBusinessinfoContrast() : new DCBusinessinfoContrast();
        contrast.setBUSINESSINFO_ID(newDCBusinessinfo.getString("BUSINESSINFO_ID"));
        contrast.setBZHL(newDCBusinessinfo.getString("CONTRAST_BZHL"));
        contrast.setCATEGORY_ID(newDCBusinessinfo.getString("CATEGORY_ID"));
        contrast.setCONTRAST_BRAND_ID(newDCBusinessinfo.getString("CONTRAST_BRAND_ID"));
        contrast.setCONTRAST_BRAND_NAME(newDCBusinessinfo.getString("CONTRAST_BRAND_NAME"));
        contrast.setCONTRAST_BUSINESS_ID(newDCBusinessinfo.getString("CONTRAST_BUSINESS_ID"));
        contrast.setCONTRAST_ORIGIN(newDCBusinessinfo.getString("CONTRAST_ORIGIN"));
        contrast.setCONTRAST_PART_ID(newDCBusinessinfo.getString("CONTRAST_PART_ID"));
        contrast.setSUPPLIER_ID(newDCBusinessinfo.getString("CONTRAST_SUPPLIER_ID"));
        contrast.setSUPPLIER_NAME(newDCBusinessinfo.getString("CONTRAST_SUPPLIER_NAME"));
        dcBusinessinfo.setDcBusinessinfoContrast(contrast);
        contrast.setDCBusinessinfo(dcBusinessinfo);

    }


    /**
     * 保存属于创建的数据,并推送待办
     * @param 
     * @param supplierPlatformItem
     */
    private void saveCreateData(JSONArray createJsonArray, SupplierPlatformItem supplierPlatformItem, Map map) {
        List<DCBusinessinfo> dcBusinessinfos = new ArrayList<>();
        for (Object o : createJsonArray) {
            JSONObject json = (JSONObject) o;
            DCBusinessinfo dcBusinessinfo = new DCBusinessinfo();
            jsonToDCBusinessinfo(json, dcBusinessinfo);
            dcBusinessinfo.setSupplierPlatformItem(supplierPlatformItem);
            dcBusinessinfos.add(dcBusinessinfo);
        }

        todos(createJsonArray, supplierPlatformItem,"create" , map);
        dcBusinessinfoRepository.save(dcBusinessinfos);
    }


    /**
     * 删除缓存表没刷新的数据, （根据定时任务的cron表达式的差值的2倍)
     * @param supplierPlatformItem
     */
    private void deleteData(SupplierPlatformItem supplierPlatformItem) {
        List condition = new ArrayList();
        condition.add(MapUtil.mapper("field","id", "operator", "EQ", "value", "auto.supplierPlatform.synTotalTask"));
        List list = ((Page<Object>)SpringManager.getBean(DomainService.class).invoke("schedule.task.findAll",
                MapUtil.mapper("condition", condition, "size", 20, "page", 0))).getContent();
        if (list == null || list.size() == 0) return;
        Map task = MapUtil.mapped(list.get(0));
        List<Map> cronExpression = dcBusinessinfoRepository.findBySupplierPlatformItemAndNotUpdate(supplierPlatformItem.getId(), getHour(task.get("cronExpression").toString()) * 2);
        if (cronExpression.size() == 0) return;
        List<Map> newList= new ArrayList<>();
        for (Map map : cronExpression) {
            Map newMap = new HashMap(map);
            newMap.put("ID", newMap.get("DCID"));
            newList.add(newMap);
        }
        try {
            todos(JSONArray.parseArray(JSON.toJSONString(cronExpression)), supplierPlatformItem, "delete", new HashMap());
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        SpringManager.getBean(DCBusinessinfoContractRepository.class).deleteBySupplierPlatformItemAndNotUpdate(
                supplierPlatformItem.getId(),getHour(task.get("cronExpression").toString()) * 2
        );
        dcBusinessinfoRepository.deleteBySupplierPlatformItemAndNotUpdate(supplierPlatformItem.getId(),
                getHour(task.get("cronExpression").toString()) * 2);
    }



    /***
     * 判断是否重要属性被修改
     */
    private boolean checkImportantUpdate(JSONObject newInHeart, JSONObject oldInHeart) {
        return importantFields.stream().anyMatch(field -> {
            return !checkEqual(newInHeart.getString(field), oldInHeart.getString(field.toUpperCase()));
        });
    }

    /***
     * 用于比较两个字符串是否相等
     */
    private boolean checkEqual(String str, String str1) {
        if (StringUtils.isEmpty(str) && StringUtils.isEmpty(str1)) return true;
        if (str == null || str1 == null) return false;
        return str.equals(str1);
    }

    public void debugging(SimpleRequest request) {
        JSONArray data = request.getJO().getJSONArray("data");
        List<DCBusinessinfoDebug> list = JSONArray.parseArray(data.toString(), DCBusinessinfoDebug.class);
        String supplierPlatformItemId = request.getJO().getString("supplierPlatformItemId");
        SupplierPlatformItem supplierPlatformItem = supplierPlatformItemRepository.findOne(supplierPlatformItemId);
        for (DCBusinessinfoDebug dcBusinessinfoDebug : list) {
            dcBusinessinfoDebug.setSupplierPlatformItem(supplierPlatformItem);
        }
        for (int i = 0; i < list.size(); i++) {
            list.get(i).setSupplierPlatformItem(supplierPlatformItem);
            list.get(i).setDCID(data.getJSONObject(i).getString("ID"));
            list.get(i).setId(sequenceService.getId(DCBusinessinfoDebug.CONST_TABLE_NAME));
        }
        SpringManager.getBean(DCBusinessinfoDebugRepository.class).save(list);
    }

    public com.apestech.framework.json.JSONObject dataCenterData(SimpleRequest request){
        com.apestech.framework.json.JSONObject json = new com.apestech.framework.json.JSONObject();
        try {
            JSONObject jo = request.getJO();
            for (Object condition : jo.getJSONArray("condition")) {
                if ("STATES".equals(JSON.toJSON(condition).getString("field")) && "debugging".equals(JSON.toJSON(condition).getString("value"))) {
                    jo.put("queryid", "supplierPlatformTodo.dataCenterData");
                }
                if ("SUPPLIER_ID".equals(JSON.toJSON(condition).getString("field"))) {
                    JSON.toJSON(condition).put("field", "SUPPLIERPLATFORM_ID");
                }
            }
            String body = jo.toString();
            json = JSON.toJSON(body);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return json;
    }

    public long getHour(String cron){
        CronExpression exp;
        try {
            exp = new CronExpression(cron);
        } catch (ParseException e) {
            throw new RuntimeException(e);
        }
        Date startDate = exp.getNextValidTimeAfter(new Date());
        Date endDate = exp.getNextValidTimeAfter(startDate);
        long nd = 1000 * 24 * 60 * 60;
        long nh = 1000 * 60 * 60;
        long diff = endDate.getTime() - startDate.getTime();
        // 计算差多少天
        long day = diff / nd;
        // 计算差多少小时
        long hour = ( diff % nd / nh ) + ( day * 24 );
        return hour;
    }
}
